package lumis.portal.serialization;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * Settings for the serialization framework (XStream in the current implementation)
 *
 * @version $Revision: 6356 $ $Date: 2007-04-05 18:02:55 -0300 (Thu, 05 Apr 2007) $
 * @since 4.0.7
 */
public class SerializationSettings implements Cloneable
{
	public static class CollectionAliasSettings
	{
		private final String fieldName;
		private final String itemAlias;
		private final Class itemClass;
		public CollectionAliasSettings(final String fieldName, final String itemAlias, final Class itemClass)
		{
			super();
			this.fieldName = fieldName;
			this.itemAlias = itemAlias;
			this.itemClass = itemClass;
			
		}
		
		public String getFieldName()
		{
			return fieldName;
		}

		public String getItemAlias()
		{
			return itemAlias;
		}

		public Class getItemClass()
		{
			return itemClass;
		}

		@Override
		public int hashCode()
		{
			final int PRIME = 31;
			int result = 1;
			result = PRIME * result + ((fieldName == null) ? 0 : fieldName.hashCode());
			result = PRIME * result + ((itemAlias == null) ? 0 : itemAlias.hashCode());
			result = PRIME * result + ((itemClass == null) ? 0 : itemClass.hashCode());
			return result;
		}
		@Override
		public boolean equals(Object obj)
		{
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			final CollectionAliasSettings other = (CollectionAliasSettings) obj;
			if (fieldName == null)
			{
				if (other.fieldName != null)
					return false;
			}
			else if (!fieldName.equals(other.fieldName))
				return false;
			if (itemAlias == null)
			{
				if (other.itemAlias != null)
					return false;
			}
			else if (!itemAlias.equals(other.itemAlias))
				return false;
			if (itemClass == null)
			{
				if (other.itemClass != null)
					return false;
			}
			else if (!itemClass.equals(other.itemClass))
				return false;
			return true;
		}
	}
	
	private final Map<Class, String> classAliases = new HashMap<Class, String>();
	private final Set<Class> converters = new HashSet<Class>();
	private final Map<Class, Set<String>> transientFields = new HashMap<Class, Set<String>>();
	private final Map<Class, Set<CollectionAliasSettings>> omittedCollections = new HashMap<Class, Set<CollectionAliasSettings>>();
	private final Map<Class, Map<String, String>> fieldAliases = new HashMap<Class, Map<String, String>>();
	public Map<Class, String> getClassAliases()
	{
		return classAliases;
	}
	public Set<Class> getConverters()
	{
		return converters;
	}
	public Map<Class, Set<String>> getTransientFields()
	{
		return transientFields;
	}

	public Set<String> getTransientFieldsForClass(Class c)
	{
		Set<String> classTransientFields = transientFields.get(c);
		if (classTransientFields == null)
		{
			classTransientFields = new HashSet<String>();
			transientFields.put(c, classTransientFields);
		}
		return classTransientFields;
	}

	public Map<Class, Set<CollectionAliasSettings>> getOmittedCollections()
	{
		return omittedCollections;
	}

	public Set<CollectionAliasSettings> getOmittedCollectionsForClass(Class c)
	{
		Set<CollectionAliasSettings> classOmittedCollections = omittedCollections.get(c);
		if (classOmittedCollections == null)
		{
			classOmittedCollections = new HashSet<CollectionAliasSettings>();
			omittedCollections.put(c, classOmittedCollections);
		}
		return classOmittedCollections;
	}

	public Map<Class, Map<String, String>> getFieldAliases()
	{
		return fieldAliases;
	}

	public Map<String, String> getFieldAliasesForClass(Class c)
	{
		Map<String, String> classFieldAliases = fieldAliases.get(c);
		if (classFieldAliases == null)
		{
			classFieldAliases = new HashMap<String, String>();
			fieldAliases.put(c, classFieldAliases);
		}
		return classFieldAliases;
	}

	@Override
	public SerializationSettings clone()
	{
		SerializationSettings newSerializationSettings = new SerializationSettings();
		newSerializationSettings.getClassAliases().putAll(classAliases);
		newSerializationSettings.getConverters().addAll(converters);
		for (Class key : transientFields.keySet())
		{
			Set<String> newValue = new HashSet<String>();
			newValue.addAll(transientFields.get(key));
			newSerializationSettings.getTransientFields().put(key, newValue);
		}
		newSerializationSettings.getOmittedCollections().putAll(omittedCollections);
		for (Class key : fieldAliases.keySet())
		{
			Map<String, String> newValue = new HashMap<String, String>();
			newValue.putAll(fieldAliases.get(key));
			newSerializationSettings.getFieldAliases().put(key, newValue);
		}
		return newSerializationSettings;
	}
}
